package org.gnyxy.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.gnyxy.constant.*;
import org.gnyxy.dto.DishDTO;
import org.gnyxy.dto.PageQueryDTO;
import org.gnyxy.entity.Dish;
import org.gnyxy.entity.DishInfo;
import org.gnyxy.entity.Material;
import org.gnyxy.exception.BaseException;
import org.gnyxy.mapper.DishInfoMapper;
import org.gnyxy.mapper.DishMapper;
import org.gnyxy.mapper.MaterialMapper;
import org.gnyxy.mapper.TypeMapper;
import org.gnyxy.result.PageResult;
import org.gnyxy.service.DishService;
import org.gnyxy.vo.DishInfoVO;
import org.gnyxy.vo.DishVO;
import org.gnyxy.vo.DishWithInfoVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class DishServiceImpl implements DishService {

    @Autowired
    private DishMapper dishMapper;
    @Autowired
    private DishInfoMapper dishInfoMapper;
    @Autowired
    private MaterialMapper materialMapper;

    /**
     * 新增菜品
     * @param dishDTO
     */
    @Override
    @Transactional
    public void add(DishDTO dishDTO) {
        // 判空
        if (dishDTO == null){
            throw new BaseException(MessageConstant.OBJECT_IS_NULL);
        }
        // 如果不传入状态默认为禁用
        if (dishDTO.getStatus() == null){
            dishDTO.setStatus(StatusConstant.DISABLE);
        }
        // 如果不传入折扣默认为不打折
        if (dishDTO.getDiscount() == null || dishDTO.getDiscount().equals(BigDecimal.ZERO)){
            dishDTO.setDiscount(DiscountConstant.DEFAULT_DISCOUNT);
        }
        if(dishDTO.getRecommended() == null){
            dishDTO.setRecommended(RecommendedConstant.DISABLE);
        }
        // 创建对象并且 Bean 拷贝
        Dish dish = new Dish();
        BeanUtils.copyProperties(dishDTO,dish);
        // 设置逻辑删除
        dish.setDeleted(DeleteConstant.IS_NOT_DELETED);
        // 执行添加Dish的SQL
        dishMapper.insert(dish);
        // 拿出dishInfo
        List<DishInfo> dishInfos = dishDTO.getDishInfoVOS();
        // 校验
        if (dishInfos == null || dishInfos.size() == 0){
            throw new BaseException(MessageConstant.OBJECT_IS_NULL);
        }
        // 设置dishId 使两个表进行关联
        dishInfos.forEach(dishInfo -> {
            dishInfo.setDishId(dish.getId());
            dishInfo.setDeleted(DeleteConstant.IS_NOT_DELETED);
        });
        // 执行添加DishInfo的SQL
        dishInfoMapper.insert(dishInfos);

        /**
         * 得出食材价格
         */
        // 定义默认价格
        BigDecimal defaultPrice = BigDecimal.ZERO;
        // 定义打折计算或自定义的价格
        BigDecimal price = BigDecimal.ZERO;
        // 定义集合并添加
        List<Long> materialIds = new ArrayList<>();
        for (DishInfo dishInfo : dishInfos){
            materialIds.add(dishInfo.getMaterialId());
        }
        // 得到默认食材价格集合
        List<BigDecimal> defaultPrices = materialMapper.getStatusTrueByIds(materialIds);
        for (int i = 0; i < defaultPrices.size(); i++) {
            // 返回 默认价格 = 默认食材价格 * 食材数量
            defaultPrice = defaultPrice.add(dishInfos.get(i).getMaterialNumber().multiply(defaultPrices.get(i)));
            // 返回 折扣价格 = 默认食材价格 * 食材数量 * 折扣价
            price = price.add(dishInfos.get(i).getMaterialNumber().multiply(defaultPrices.get(i)).multiply(dish.getDiscount()));
        }
        // 设置价格和默认价格
        dish.setDefaultPrice(defaultPrice);
        dish.setPrice(price);
        dishMapper.update(dish);
    }

    /**
     * 根据id删除菜品
     * @param id
     */
    @Override
    @Transactional
    public void delete(Long id) {
        // id不为空
        if (id == null){
            throw new BaseException(MessageConstant.ID_IS_NULL);
        }
        // 根据dishId查询 dishInfo
        List<DishInfo> dishInfos = dishInfoMapper.getByDishId(id);
        // 校验
        if (dishInfos == null || dishInfos.size() == 0){
            throw new BaseException(MessageConstant.OBJECT_IS_NULL);
        }
        // 删除 ids
        for (DishInfo dishInfo : dishInfos){
            dishInfo.setDeleted(DeleteConstant.IS_DELETED);
            dishInfoMapper.update(dishInfo);
        }
        // 查询 dish
        Dish dish = dishMapper.getById(id);
        dish.setDeleted(DeleteConstant.IS_DELETED);
        dishMapper.update(dish);
    }

    /**
     * 根据id获取菜品
     * @param id
     * @return
     */
    @Override
    public DishWithInfoVO getById(Long id) {
        // id不为空
        if (id == null){
            throw new BaseException(MessageConstant.ID_IS_NULL);
        }
        DishWithInfoVO dishWithTypeNameVOById = dishMapper.getDishWithTypeNameVOById(id);
        List<DishInfo> dishInfos = dishInfoMapper.getByDishId(id);

        List<DishInfoVO> dishInfoVOS = new ArrayList<>();
        List<Long> materialIds = new ArrayList<>();
        for (DishInfo dishInfo : dishInfos) {
            DishInfoVO dishInfoVO = new DishInfoVO();
            BeanUtils.copyProperties(dishInfo,dishInfoVO);
            dishInfoVOS.add(dishInfoVO);
            materialIds.add(dishInfo.getMaterialId());
        }
        List<Material> materials = materialMapper.getByIds(materialIds);
        for (DishInfoVO dishInfoVO : dishInfoVOS) {
            for (Material material : materials) {
                if (material.getId().equals(dishInfoVO.getMaterialId())){
                    dishInfoVO.setMaterialName(material.getName())
                            .setImage(material.getImage())
                            .setUnit(material.getUnit())
                            .setDefaultPrice(material.getDefaultPrice())
                            .setRange(material.getRange())
                            .setPrice(material.getPrice());

                }
            }
        }
        dishWithTypeNameVOById.setDishInfoVOS(dishInfoVOS);

//        BeanUtils.copyProperties(dish,dishWithInfoVO);
//        dishWithInfoVO.setDishInfos(dishInfos);
//        dishWithTypeNameVOById.setDishInfos(dishInfos);
        return dishWithTypeNameVOById;
    }

    /**
     * 更新菜品
     * @param dishDTO
     * @return
     */
    @Override
    @Transactional
    public void update(DishDTO dishDTO) {
        // 判空
        if (dishDTO == null){
            throw new BaseException(MessageConstant.OBJECT_IS_NULL);
        }

        if(dishDTO.getRecommended() == null){
            dishDTO.setRecommended(RecommendedConstant.DISABLE);
        }

        List<DishInfo> dishInfos = dishDTO.getDishInfoVOS();
        // 判空
        if (dishInfos == null || dishInfos.size() == 0){
            throw new BaseException(MessageConstant.OBJECT_IS_NULL);
        }
        // 更新dishInfo的SQL
        for (DishInfo dishInfo : dishInfos){
            dishInfo.setDeleted(DeleteConstant.IS_NOT_DELETED);
            dishInfoMapper.update(dishInfo);
        }
        /**
         * 更新Dish
         */
        Dish dish = new Dish();
        // 拷贝并设置逻辑删除
        BeanUtils.copyProperties(dishDTO,dish);
        dish.setDeleted(DeleteConstant.IS_NOT_DELETED);
        /**
         * 得出食材价格
         */
        // 定义默认价格
        BigDecimal defaultPrice = BigDecimal.ZERO;
        // 定义打折计算或自定义的价格
        BigDecimal price = BigDecimal.ZERO;
        // 定义集合并添加
        List<Long> materialIds = new ArrayList<>();
        for (DishInfo dishInfo : dishInfos){
            materialIds.add(dishInfo.getMaterialId());
        }
        // 得到默认食材价格集合
        List<BigDecimal> defaultPrices = materialMapper.getStatusTrueByIds(materialIds);
        for (int i = 0; i < defaultPrices.size(); i++) {
            // 返回 默认价格 = 默认食材价格 * 食材数量
            defaultPrice = defaultPrice.add(dishInfos.get(i).getMaterialNumber().multiply(defaultPrices.get(i)));
            // 返回 折扣价格 = 默认食材价格 * 食材数量 * 折扣价
            price = price.add(dishInfos.get(i).getMaterialNumber().multiply(defaultPrices.get(i)).multiply(dish.getDiscount()));
        }
        // 设置价格和默认价格
        dish.setDefaultPrice(defaultPrice);
        dish.setPrice(price);
        dishMapper.update(dish);
    }

    /**
     * 分页查询
     * @param pageQueryDTO
     * @return
     */
    @Override
    public PageResult page(PageQueryDTO pageQueryDTO) {
        PageHelper.startPage(pageQueryDTO.getPage(), pageQueryDTO.getPageSize());
        Page<Dish> dishes = dishMapper.pageQuery(pageQueryDTO);
        return new PageResult(dishes.getTotal(),dishes.getResult());
    }

    /**
     * 设置状态
     * @param status
     * @param id
     * @return
     */
    @Override
    public void setStatus(Integer status, Long id) {
        // 校验
        if (id == null){
            throw new BaseException(MessageConstant.ID_IS_NULL);
        }
        Dish dish = dishMapper.getById(id);
        dish.setStatus(status);
        dishMapper.update(dish);
    }

    /**
     * 设置价格
     * @param price
     * @param id
     */
    @Override
    public void setPrice(BigDecimal price, Long id) {
        // 校验
        if (id == null){
            throw new BaseException(MessageConstant.ID_IS_NULL);
        }
        if (price == null){
            throw new BaseException(MessageConstant.OBJECT_IS_NULL);
        }
        Dish dish = dishMapper.getById(id);
        dish.setPrice(price);
        dishMapper.update(dish);
    }

    /**
     * 分类查询
     * @param dish
     * @return
     */
    @Override
    public List<DishVO> getByTypeIdAndStatus(Dish dish) {
        //校验
        if (dish.getTypeId() == null){
            throw new BaseException(MessageConstant.ID_IS_NULL);
        }
        List<Dish> dishes = dishMapper.getByTypeIdAndStatus(dish);
        // 替换成VO
        return dishes.stream().map(dish1 -> {
            DishVO dishVO = new DishVO();
            BeanUtils.copyProperties(dish1,dishVO);
            return dishVO;
        }).collect(Collectors.toList());
    }

    /**
     * 根据菜名搜索菜品
     * @param name
     * @return
     */
    @Override
    public List<DishVO> getDishByName(String name) {
        // 校验
        if (name == null){
            throw new BaseException(MessageConstant.OBJECT_IS_NULL);
        }
        // 根据姓名查询并且Bean拷贝
        List<Dish> dishes = dishMapper.getByName(name);
        // 替换成VO
        return dishes.stream().map(dish1 -> {
            DishVO dishVO = new DishVO();
            BeanUtils.copyProperties(dish1,dishVO);
            return dishVO;
        }).collect(Collectors.toList());
    }

    /**
     * 查询所有菜品
     * @return
     */
    @Override
    public List<DishVO> getAll() {
        // 校验
        List<Dish> dishes = dishMapper.getAll();
        // 转换成VO
        return dishes.stream().map(dish -> {
            DishVO dishVO = new DishVO();
            BeanUtils.copyProperties(dish,dishVO);
            return dishVO;
        }).collect(Collectors.toList());
    }

    /**
     * 根据id获取菜品详情
     * @param id
     * @return
     */
    @Override
    public DishWithInfoVO getDishAndInfo(Long id) {
        // 校验
        if (id == null){
            throw new BaseException(MessageConstant.ID_IS_NULL);
        }
        // dish和dishInfo查询并拷贝
        DishWithInfoVO dishWithInfoVO = dishMapper.getByIdAndStatus(id);
        List<DishInfo> dishInfos = dishInfoMapper.getByDishId(id);
        if (dishWithInfoVO == null || dishInfos == null){
            throw new BaseException(MessageConstant.DISH_IS_NULL);
        }

        List<DishInfoVO> dishInfoVOS = new ArrayList<>();
        List<Long> materialIds = new ArrayList<>();
        for (DishInfo dishInfo : dishInfos) {
            DishInfoVO dishInfoVO = new DishInfoVO();
            BeanUtils.copyProperties(dishInfo,dishInfoVO);
            dishInfoVOS.add(dishInfoVO);
            materialIds.add(dishInfo.getMaterialId());
        }
        List<Material> materials = materialMapper.getByIds(materialIds);
        for (DishInfoVO dishInfoVO : dishInfoVOS) {
            for (Material material : materials) {
                if (material.getId().equals(dishInfoVO.getMaterialId())){
                    dishInfoVO.setMaterialName(material.getName())
                            .setImage(material.getImage())
                            .setUnit(material.getUnit())
                            .setDefaultPrice(material.getDefaultPrice())
                            .setRange(material.getRange())
                            .setPrice(material.getPrice());

                }
            }
        }
        dishWithInfoVO.setDishInfoVOS(dishInfoVOS);

//        BeanUtils.copyProperties(dish,dishWithInfoVO);
//        dishWithInfoVO.setDishInfos(dishInfos);
        return dishWithInfoVO;
    }
}
